జావాస్క్రిప్ట్లో నిజమైన మల్టీథ్రెడింగ్ను అన్లాక్ చేయండి. ఈ సమగ్ర గైడ్ షేర్డ్అర్రేబఫర్, అటామిక్స్, వెబ్ వర్కర్లు మరియు అధిక-పనితీరు గల వెబ్ అప్లికేషన్ల కోసం భద్రతా అవసరాలను వివరిస్తుంది.
జావాస్క్రిప్ట్ షేర్డ్అర్రేబఫర్: వెబ్లో కాంకరెంట్ ప్రోగ్రామింగ్పై ఒక లోతైన విశ్లేషణ
దశాబ్దాలుగా, జావాస్క్రిప్ట్ యొక్క సింగిల్-థ్రెడెడ్ స్వభావం దాని సరళతకు మరియు అదే సమయంలో ఒక ముఖ్యమైన పనితీరు సమస్యకు మూలంగా ఉంది. ఈవెంట్ లూప్ మోడల్ చాలా UI-ఆధారిత పనులకు అద్భుతంగా పనిచేస్తుంది, కానీ గణనతో కూడిన తీవ్రమైన ఆపరేషన్లతో ఇది ఇబ్బంది పడుతుంది. ఎక్కువ సేపు జరిగే లెక్కలు బ్రౌజర్ను స్తంభింపజేసి, వినియోగదారునికి నిరాశాజనకమైన అనుభవాన్ని కలిగిస్తాయి. వెబ్ వర్కర్లు స్క్రిప్ట్లను బ్యాక్గ్రౌండ్లో నడపడానికి అనుమతించడం ద్వారా పాక్షిక పరిష్కారాన్ని అందించినప్పటికీ, వాటికి ఒక పెద్ద పరిమితి ఉంది: అసమర్థమైన డేటా కమ్యూనికేషన్.
ఇక్కడే SharedArrayBuffer
(SAB) ప్రవేశిస్తుంది. ఇది వెబ్లో థ్రెడ్ల మధ్య నిజమైన, తక్కువ-స్థాయి మెమరీ షేరింగ్ను పరిచయం చేయడం ద్వారా ఆటను ప్రాథమికంగా మారుస్తుంది. Atomics
ఆబ్జెక్ట్తో జతకట్టినప్పుడు, SAB నేరుగా బ్రౌజర్లో అధిక-పనితీరు, కాంకరెంట్ అప్లికేషన్ల యొక్క కొత్త శకానికి తలుపులు తెరుస్తుంది. అయితే, గొప్ప శక్తితో పాటు గొప్ప బాధ్యత మరియు సంక్లిష్టత కూడా వస్తుంది.
ఈ గైడ్ మిమ్మల్ని జావాస్క్రిప్ట్లో కాంకరెంట్ ప్రోగ్రామింగ్ ప్రపంచంలోకి లోతుగా తీసుకువెళ్తుంది. మనకు ఇది ఎందుకు అవసరం, SharedArrayBuffer
మరియు Atomics
ఎలా పనిచేస్తాయి, మీరు తప్పనిసరిగా పాటించాల్సిన కీలక భద్రతా పరిగణనలు మరియు మీరు ప్రారంభించడానికి ఆచరణాత్మక ఉదాహరణలను మనం అన్వేషిస్తాము.
పాత ప్రపంచం: జావాస్క్రిప్ట్ యొక్క సింగిల్-థ్రెడెడ్ మోడల్ మరియు దాని పరిమితులు
పరిష్కారాన్ని అభినందించడానికి ముందు, మనం సమస్యను పూర్తిగా అర్థం చేసుకోవాలి. బ్రౌజర్లో జావాస్క్రిప్ట్ ఎగ్జిక్యూషన్ సాంప్రదాయకంగా ఒకే థ్రెడ్లో జరుగుతుంది, దీనిని తరచుగా "మెయిన్ థ్రెడ్" లేదా "UI థ్రెడ్" అని పిలుస్తారు.
ఈవెంట్ లూప్
మెయిన్ థ్రెడ్ అన్నింటికీ బాధ్యత వహిస్తుంది: మీ జావాస్క్రిప్ట్ కోడ్ను అమలు చేయడం, పేజీని రెండర్ చేయడం, వినియోగదారు ఇంటరాక్షన్లకు (క్లిక్లు మరియు స్క్రోల్స్ వంటివి) ప్రతిస్పందించడం మరియు CSS యానిమేషన్లను నడపడం. ఇది ఈ పనులను ఒక ఈవెంట్ లూప్ ఉపయోగించి నిర్వహిస్తుంది, ఇది నిరంతరం సందేశాల (పనుల) క్యూను ప్రాసెస్ చేస్తుంది. ఒక పని పూర్తి కావడానికి చాలా సమయం పడితే, అది మొత్తం క్యూను బ్లాక్ చేస్తుంది. మరేమీ జరగదు—UI స్తంభించిపోతుంది, యానిమేషన్లు ఆగిపోతాయి, మరియు పేజీ ప్రతిస్పందించదు.
వెబ్ వర్కర్లు: సరైన దిశలో ఒక అడుగు
ఈ సమస్యను తగ్గించడానికి వెబ్ వర్కర్లను పరిచయం చేశారు. ఒక వెబ్ వర్కర్ అంటే వేరే బ్యాక్గ్రౌండ్ థ్రెడ్లో నడుస్తున్న ఒక స్క్రిప్ట్. మీరు భారీ గణనలను ఒక వర్కర్కు అప్పగించవచ్చు, దీనివల్ల మెయిన్ థ్రెడ్ యూజర్ ఇంటర్ఫేస్ను నిర్వహించడానికి స్వేచ్ఛగా ఉంటుంది.
మెయిన్ థ్రెడ్ మరియు ఒక వర్కర్ మధ్య కమ్యూనికేషన్ postMessage()
API ద్వారా జరుగుతుంది. మీరు డేటాను పంపినప్పుడు, అది స్ట్రక్చర్డ్ క్లోన్ అల్గారిథమ్ ద్వారా నిర్వహించబడుతుంది. అంటే డేటా సీరియలైజ్ చేయబడి, కాపీ చేయబడి, ఆపై వర్కర్ సందర్భంలో డీసీరియలైజ్ చేయబడుతుంది. ఇది ప్రభావవంతమైనదే అయినప్పటికీ, పెద్ద డేటాసెట్లకు ఈ ప్రక్రియలో గణనీయమైన ప్రతికూలతలు ఉన్నాయి:
- పనితీరు ఓవర్హెడ్: థ్రెడ్ల మధ్య మెగాబైట్లు లేదా గిగాబైట్ల డేటాను కాపీ చేయడం నెమ్మదిగా మరియు CPU-ఇంటెన్సివ్గా ఉంటుంది.
- మెమరీ వినియోగం: ఇది మెమరీలో డేటా యొక్క డూప్లికేట్ను సృష్టిస్తుంది, ఇది మెమరీ-పరిమిత పరికరాలకు ఒక పెద్ద సమస్య కావచ్చు.
బ్రౌజర్లో ఒక వీడియో ఎడిటర్ను ఊహించుకోండి. ప్రాసెసింగ్ కోసం ఒక పూర్తి వీడియో ఫ్రేమ్ను (ఇది అనేక మెగాబైట్లు ఉండవచ్చు) సెకనుకు 60 సార్లు ఒక వర్కర్కు పంపడం మరియు తిరిగి పొందడం చాలా ఖరీదైనది. ఈ సమస్యను పరిష్కరించడానికే SharedArrayBuffer
రూపొందించబడింది.
గేమ్-ఛేంజర్: SharedArrayBuffer
పరిచయం
ఒక SharedArrayBuffer
అనేది ArrayBuffer
లాంటి ఒక స్థిర-పొడవు గల రా బైనరీ డేటా బఫర్. కీలకమైన వ్యత్యాసం ఏమిటంటే, ఒక SharedArrayBuffer
బహుళ థ్రెడ్ల మధ్య (ఉదా., మెయిన్ థ్రెడ్ మరియు ఒకటి లేదా అంతకంటే ఎక్కువ వెబ్ వర్కర్లు) పంచుకోబడుతుంది. మీరు postMessage()
ఉపయోగించి ఒక SharedArrayBuffer
ను "పంపినప్పుడు", మీరు ఒక కాపీని పంపడం లేదు; మీరు అదే మెమరీ బ్లాక్కు ఒక రిఫరెన్స్ను పంపుతున్నారు.
అంటే ఒక థ్రెడ్ బఫర్ డేటాలో చేసిన ఏవైనా మార్పులు దానికి రిఫరెన్స్ ఉన్న అన్ని ఇతర థ్రెడ్లకు తక్షణమే కనిపిస్తాయి. ఇది ఖరీదైన కాపీ-మరియు-సీరియలైజ్ దశను తొలగిస్తుంది, దాదాపు తక్షణ డేటా షేరింగ్ను సాధ్యం చేస్తుంది.
దీనిని ఇలా ఆలోచించండి:
postMessage()
తో వెబ్ వర్కర్లు: ఇది ఇద్దరు సహోద్యోగులు ఒక డాక్యుమెంట్పై పనిచేస్తూ ఇమెయిల్ ద్వారా కాపీలను పంపుకోవడం లాంటిది. ప్రతి మార్పుకు ఒక కొత్త కాపీని పంపడం అవసరం.SharedArrayBuffer
తో వెబ్ వర్కర్లు: ఇది ఇద్దరు సహోద్యోగులు ఒకే డాక్యుమెంట్పై ఒక షేర్డ్ ఆన్లైన్ ఎడిటర్లో (గూగుల్ డాక్స్ వంటివి) పనిచేయడం లాంటిది. మార్పులు ఇద్దరికీ నిజ-సమయంలో కనిపిస్తాయి.
షేర్డ్ మెమరీ యొక్క ప్రమాదం: రేస్ కండిషన్స్
తక్షణ మెమరీ షేరింగ్ శక్తివంతమైనది, కానీ ఇది కాంకరెంట్ ప్రోగ్రామింగ్ ప్రపంచం నుండి ఒక క్లాసిక్ సమస్యను కూడా పరిచయం చేస్తుంది: రేస్ కండిషన్స్.
ఒక రేస్ కండిషన్ ఎప్పుడు సంభవిస్తుందంటే, బహుళ థ్రెడ్లు ఒకే షేర్డ్ డేటాను ఏకకాలంలో యాక్సెస్ చేయడానికి మరియు సవరించడానికి ప్రయత్నించినప్పుడు, మరియు తుది ఫలితం అవి ఏ అనూహ్య క్రమంలో అమలు అవుతాయో దానిపై ఆధారపడి ఉంటుంది. ఒక SharedArrayBuffer
లో నిల్వ చేయబడిన ఒక సాధారణ కౌంటర్ను పరిగణించండి. మెయిన్ థ్రెడ్ మరియు ఒక వర్కర్ రెండూ దానిని ఇంక్రిమెంట్ చేయాలనుకుంటున్నాయి.
- థ్రెడ్ A ప్రస్తుత విలువను చదువుతుంది, అది 5.
- థ్రెడ్ A కొత్త విలువను వ్రాసే ముందు, ఆపరేటింగ్ సిస్టమ్ దానిని పాజ్ చేసి థ్రెడ్ Bకి మారుస్తుంది.
- థ్రెడ్ B ప్రస్తుత విలువను చదువుతుంది, అది ఇప్పటికీ 5.
- థ్రెడ్ B కొత్త విలువను (6) లెక్కించి, దానిని తిరిగి మెమరీకి వ్రాస్తుంది.
- సిస్టమ్ తిరిగి థ్రెడ్ Aకి మారుతుంది. థ్రెడ్ B ఏమీ చేయలేదని దానికి తెలియదు. అది ఎక్కడ ఆగిపోయిందో అక్కడి నుండి తిరిగి ప్రారంభించి, దాని కొత్త విలువను (5 + 1 = 6) లెక్కించి, 6 ను తిరిగి మెమరీకి వ్రాస్తుంది.
కౌంటర్ రెండుసార్లు ఇంక్రిమెంట్ చేయబడినప్పటికీ, తుది విలువ 6, 7 కాదు. ఆపరేషన్లు అటామిక్ కావు—అవి అంతరాయం కలిగించేవి, ఇది డేటా నష్టానికి దారితీసింది. సరిగ్గా ఈ కారణంగానే మీరు SharedArrayBuffer
ను దాని కీలక భాగస్వామి లేకుండా ఉపయోగించలేరు: అదే Atomics
ఆబ్జెక్ట్.
షేర్డ్ మెమరీ యొక్క సంరక్షకుడు: Atomics
ఆబ్జెక్ట్
Atomics
ఆబ్జెక్ట్ SharedArrayBuffer
ఆబ్జెక్ట్లపై అటామిక్ ఆపరేషన్లు చేయడానికి స్టాటిక్ మెథడ్స్ యొక్క ఒక సెట్ను అందిస్తుంది. ఒక అటామిక్ ఆపరేషన్ ఏ ఇతర ఆపరేషన్ ద్వారా అంతరాయం కలగకుండా పూర్తిగా నిర్వహించబడుతుందని హామీ ఇవ్వబడుతుంది. ఇది పూర్తిగా జరుగుతుంది లేదా అస్సలు జరగదు.
Atomics
ఉపయోగించడం ద్వారా షేర్డ్ మెమరీపై రీడ్-మాడిఫై-రైట్ ఆపరేషన్లు సురక్షితంగా నిర్వహించబడతాయని నిర్ధారించుకోవడం ద్వారా రేస్ కండిషన్స్ను నివారిస్తుంది.
కీలకమైన Atomics
మెథడ్స్
Atomics
అందించే కొన్ని ముఖ్యమైన మెథడ్స్ను చూద్దాం.
Atomics.load(typedArray, index)
: ఒక నిర్దిష్ట ఇండెక్స్లోని విలువను అటామిక్గా చదివి దానిని తిరిగి ఇస్తుంది. ఇది మీరు పూర్తి, పాడవని విలువను చదువుతున్నారని నిర్ధారిస్తుంది.Atomics.store(typedArray, index, value)
: ఒక నిర్దిష్ట ఇండెక్స్లో ఒక విలువను అటామిక్గా నిల్వ చేసి ఆ విలువను తిరిగి ఇస్తుంది. ఇది రైట్ ఆపరేషన్కు అంతరాయం కలగకుండా చూస్తుంది.Atomics.add(typedArray, index, value)
: ఇచ్చిన ఇండెక్స్లోని విలువకు ఒక విలువను అటామిక్గా కలుపుతుంది. ఇది ఆ స్థానంలోని అసలు విలువను తిరిగి ఇస్తుంది. ఇదిx += value
కు అటామిక్ సమానమైనది.Atomics.sub(typedArray, index, value)
: ఇచ్చిన ఇండెక్స్లోని విలువ నుండి ఒక విలువను అటామిక్గా తీసివేస్తుంది.Atomics.compareExchange(typedArray, index, expectedValue, replacementValue)
: ఇది ఒక శక్తివంతమైన షరతులతో కూడిన రైట్. ఇదిindex
వద్ద ఉన్న విలువexpectedValue
కు సమానంగా ఉందో లేదో తనిఖీ చేస్తుంది. అలా అయితే, దానినిreplacementValue
తో భర్తీ చేసి అసలుexpectedValue
ను తిరిగి ఇస్తుంది. లేకపోతే, ఏమీ చేయకుండా ప్రస్తుత విలువను తిరిగి ఇస్తుంది. ఇది లాక్స్ వంటి మరింత సంక్లిష్టమైన సింక్రొనైజేషన్ ప్రిమిటివ్లను అమలు చేయడానికి ఒక ప్రాథమిక బిల్డింగ్ బ్లాక్.
సింక్రొనైజేషన్: సాధారణ ఆపరేషన్లకు మించి
కొన్నిసార్లు మీకు కేవలం సురక్షితమైన రీడింగ్ మరియు రైటింగ్ కంటే ఎక్కువ అవసరం. థ్రెడ్లు ఒకదానికొకటి సమన్వయం చేసుకోవాలి మరియు ఒకదాని కోసం మరొకటి వేచి ఉండాలి. ఒక సాధారణ యాంటీ-ప్యాటర్న్ "బిజీ-వెయిటింగ్", ఇక్కడ ఒక థ్రెడ్ ఒక టైట్ లూప్లో కూర్చుని, ఒక మార్పు కోసం నిరంతరం ఒక మెమరీ లొకేషన్ను తనిఖీ చేస్తుంది. ఇది CPU సైకిల్స్ను వృధా చేస్తుంది మరియు బ్యాటరీ లైఫ్ను తగ్గిస్తుంది.
Atomics
wait()
మరియు notify()
తో చాలా సమర్థవంతమైన పరిష్కారాన్ని అందిస్తుంది.
Atomics.wait(typedArray, index, value, timeout)
: ఇది ఒక థ్రెడ్ను నిద్రపోవాలని చెబుతుంది. ఇదిindex
వద్ద ఉన్న విలువ ఇప్పటికీvalue
గా ఉందో లేదో తనిఖీ చేస్తుంది. అలా అయితే,Atomics.notify()
ద్వారా మేల్కొల్పబడే వరకు లేదా ఐచ్ఛికtimeout
(మిల్లీసెకన్లలో) పూర్తయ్యే వరకు థ్రెడ్ నిద్రపోతుంది.index
వద్ద ఉన్న విలువ ఇప్పటికే మారిపోయి ఉంటే, అది వెంటనే తిరిగి వస్తుంది. ఇది చాలా సమర్థవంతమైనది ఎందుకంటే నిద్రపోతున్న థ్రెడ్ దాదాపు CPU వనరులను వినియోగించుకోదు.Atomics.notify(typedArray, index, count)
: ఇదిAtomics.wait()
ద్వారా ఒక నిర్దిష్ట మెమరీ లొకేషన్లో నిద్రపోతున్న థ్రెడ్లను మేల్కొల్పడానికి ఉపయోగించబడుతుంది. ఇది గరిష్టంగాcount
నిరీక్షిస్తున్న థ్రెడ్లను మేల్కొల్పుతుంది (లేదాcount
అందించకపోతే లేదాInfinity
అయితే అన్నింటినీ).
అన్నింటినీ కలిపి: ఒక ఆచరణాత్మక గైడ్
ఇప్పుడు మనం సిద్ధాంతాన్ని అర్థం చేసుకున్నాము, SharedArrayBuffer
ఉపయోగించి ఒక పరిష్కారాన్ని అమలు చేసే దశలను చూద్దాం.
దశ 1: భద్రతా అవసరం - క్రాస్-ఆరిజిన్ ఐసోలేషన్
ఇది డెవలపర్లకు అత్యంత సాధారణ అడ్డంకి. భద్రతా కారణాల వల్ల, SharedArrayBuffer
కేవలం క్రాస్-ఆరిజిన్ ఐసోలేటెడ్ స్థితిలో ఉన్న పేజీలలో మాత్రమే అందుబాటులో ఉంటుంది. ఇది స్పెక్టర్ వంటి స్పెక్యులేటివ్ ఎగ్జిక్యూషన్ దుర్బలత్వాలను తగ్గించడానికి ఒక భద్రతా చర్య, ఇది షేర్డ్ మెమరీ ద్వారా సాధ్యమయ్యే హై-రిజల్యూషన్ టైమర్లను ఉపయోగించి ఆరిజిన్ల మధ్య డేటాను లీక్ చేసే అవకాశం ఉంది.
క్రాస్-ఆరిజిన్ ఐసోలేషన్ను ప్రారంభించడానికి, మీరు మీ వెబ్ సర్వర్ను మీ ప్రధాన డాక్యుమెంట్ కోసం రెండు నిర్దిష్ట HTTP హెడర్లను పంపేలా కాన్ఫిగర్ చేయాలి:
Cross-Origin-Opener-Policy: same-origin
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin
(COOP): మీ డాక్యుమెంట్ బ్రౌజింగ్ కాంటెక్స్ట్ను ఇతర డాక్యుమెంట్ల నుండి వేరు చేస్తుంది, వాటిని మీ విండో ఆబ్జెక్ట్తో నేరుగా ఇంటరాక్ట్ అవ్వకుండా నిరోధిస్తుంది.Cross-Origin-Embedder-Policy: require-corp
(COEP): మీ పేజీ ద్వారా లోడ్ చేయబడిన అన్ని సబ్రిసోర్స్లు (చిత్రాలు, స్క్రిప్ట్లు మరియు ఐఫ్రేమ్లు వంటివి) ఒకే ఆరిజిన్ నుండి ఉండాలి లేదాCross-Origin-Resource-Policy
హెడర్ లేదా CORSతో స్పష్టంగా క్రాస్-ఆరిజిన్ లోడబుల్గా గుర్తించబడాలి.
దీనిని సెటప్ చేయడం సవాలుగా ఉంటుంది, ప్రత్యేకించి మీరు అవసరమైన హెడర్లను అందించని థర్డ్-పార్టీ స్క్రిప్ట్లు లేదా వనరులపై ఆధారపడి ఉంటే. మీ సర్వర్ను కాన్ఫిగర్ చేసిన తర్వాత, బ్రౌజర్ కన్సోల్లో self.crossOriginIsolated
ప్రాపర్టీని తనిఖీ చేయడం ద్వారా మీ పేజీ ఐసోలేట్ చేయబడిందో లేదో మీరు ధృవీకరించవచ్చు. ఇది true
గా ఉండాలి.
దశ 2: బఫర్ను సృష్టించడం మరియు పంచుకోవడం
మీ ప్రధాన స్క్రిప్ట్లో, మీరు SharedArrayBuffer
మరియు దానిపై ఒక "వ్యూ"ను Int32Array
వంటి TypedArray
ఉపయోగించి సృష్టిస్తారు.
main.js:
// ముందుగా క్రాస్-ఆరిజిన్ ఐసోలేషన్ కోసం తనిఖీ చేయండి!
if (!self.crossOriginIsolated) {
console.error("ఈ పేజీ క్రాస్-ఆరిజిన్ ఐసోలేటెడ్ కాదు. SharedArrayBuffer అందుబాటులో ఉండదు.");
} else {
// ఒక 32-బిట్ ఇంటిజర్ కోసం ఒక షేర్డ్ బఫర్ను సృష్టించండి.
const buffer = new SharedArrayBuffer(4);
// బఫర్పై ఒక వ్యూను సృష్టించండి. అన్ని అటామిక్ ఆపరేషన్లు వ్యూపై జరుగుతాయి.
const int32Array = new Int32Array(buffer);
// ఇండెక్స్ 0 వద్ద విలువను ఇనిషియలైజ్ చేయండి.
int32Array[0] = 0;
// ఒక కొత్త వర్కర్ను సృష్టించండి.
const worker = new Worker('worker.js');
// షేర్డ్ బఫర్ను వర్కర్కు పంపండి. ఇది రిఫరెన్స్ ట్రాన్స్ఫర్, కాపీ కాదు.
worker.postMessage({ buffer });
// వర్కర్ నుండి సందేశాల కోసం వినండి.
worker.onmessage = (event) => {
console.log(`వర్కర్ పూర్తి చేసినట్లు నివేదించింది. తుది విలువ: ${Atomics.load(int32Array, 0)}`);
};
}
దశ 3: వర్కర్లో అటామిక్ ఆపరేషన్లు చేయడం
వర్కర్ బఫర్ను స్వీకరించి ఇప్పుడు దానిపై అటామిక్ ఆపరేషన్లు చేయగలదు.
worker.js:
self.onmessage = (event) => {
const { buffer } = event.data;
const int32Array = new Int32Array(buffer);
console.log("వర్కర్ షేర్డ్ బఫర్ను స్వీకరించింది.");
// కొన్ని అటామిక్ ఆపరేషన్లు చేద్దాం.
for (let i = 0; i < 1000000; i++) {
// షేర్డ్ విలువను సురక్షితంగా ఇంక్రిమెంట్ చేయండి.
Atomics.add(int32Array, 0, 1);
}
console.log("వర్కర్ ఇంక్రిమెంట్ చేయడం పూర్తి చేసింది.");
// మనం పూర్తి చేశామని ప్రధాన థ్రెడ్కు సిగ్నల్ పంపండి.
self.postMessage({ done: true });
};
దశ 4: మరింత ఆధునిక ఉదాహరణ - సింక్రొనైజేషన్తో ప్యారలల్ సమ్మేషన్
మరింత వాస్తవిక సమస్యను పరిష్కరిద్దాం: బహుళ వర్కర్లను ఉపయోగించి చాలా పెద్ద సంఖ్యల అర్రేను కూడటం. సమర్థవంతమైన సింక్రొనైజేషన్ కోసం మనం Atomics.wait()
మరియు Atomics.notify()
ఉపయోగిస్తాము.
మన షేర్డ్ బఫర్లో మూడు భాగాలు ఉంటాయి:
- ఇండెక్స్ 0: ఒక స్టేటస్ ఫ్లాగ్ (0 = ప్రాసెసింగ్లో ఉంది, 1 = పూర్తయింది).
- ఇండెక్స్ 1: ఎంత మంది వర్కర్లు పూర్తి చేశారో తెలిపే ఒక కౌంటర్.
- ఇండెక్స్ 2: తుది మొత్తం.
main.js:
if (self.crossOriginIsolated) {
const NUM_WORKERS = 4;
const DATA_SIZE = 10_000_000;
// [status, workers_finished, result_low, result_high]
// పెద్ద మొత్తాల కోసం ఓవర్ఫ్లోను నివారించడానికి ఫలితం కోసం రెండు 32-బిట్ ఇంటిజర్లను ఉపయోగిస్తాము.
const sharedBuffer = new SharedArrayBuffer(4 * 4); // 4 ఇంటిజర్లు
const sharedArray = new Int32Array(sharedBuffer);
// ప్రాసెస్ చేయడానికి కొంత యాదృచ్ఛిక డేటాను ఉత్పత్తి చేయండి
const data = new Uint8Array(DATA_SIZE);
for (let i = 0; i < DATA_SIZE; i++) {
data[i] = Math.floor(Math.random() * 10);
}
const chunkSize = Math.ceil(DATA_SIZE / NUM_WORKERS);
for (let i = 0; i < NUM_WORKERS; i++) {
const worker = new Worker('sum_worker.js');
const start = i * chunkSize;
const end = Math.min(start + chunkSize, DATA_SIZE);
// వర్కర్ యొక్క డేటా చంక్ కోసం ఒక నాన్-షేర్డ్ వ్యూను సృష్టించండి
const dataChunk = data.subarray(start, end);
worker.postMessage({
sharedBuffer,
dataChunk // ఇది కాపీ చేయబడింది
});
}
console.log('ప్రధాన థ్రెడ్ ఇప్పుడు వర్కర్లు పూర్తి చేయడం కోసం వేచి ఉంది...');
// ఇండెక్స్ 0 వద్ద ఉన్న స్టేటస్ ఫ్లాగ్ 1 అయ్యే వరకు వేచి ఉండండి
// ఇది ఒక వైల్ లూప్ కంటే చాలా ఉత్తమమైనది!
Atomics.wait(sharedArray, 0, 0); // sharedArray[0] 0 అయితే వేచి ఉండండి
console.log('ప్రధాన థ్రెడ్ మేల్కొంది!');
const finalSum = Atomics.load(sharedArray, 2);
console.log(`తుది ప్యారలల్ మొత్తం: ${finalSum}`);
} else {
console.error('పేజీ క్రాస్-ఆరిజిన్ ఐసోలేటెడ్ కాదు.');
}
sum_worker.js:
self.onmessage = ({ data }) => {
const { sharedBuffer, dataChunk } = data;
const sharedArray = new Int32Array(sharedBuffer);
// ఈ వర్కర్ యొక్క చంక్ కోసం మొత్తాన్ని లెక్కించండి
let localSum = 0;
for (let i = 0; i < dataChunk.length; i++) {
localSum += dataChunk[i];
}
// స్థానిక మొత్తాన్ని షేర్డ్ మొత్తానికి అటామిక్గా జోడించండి
Atomics.add(sharedArray, 2, localSum);
// 'వర్కర్స్ ఫినిష్డ్' కౌంటర్ను అటామిక్గా ఇంక్రిమెంట్ చేయండి
const finishedCount = Atomics.add(sharedArray, 1, 1) + 1;
// ఇది పూర్తి చేసిన చివరి వర్కర్ అయితే...
const NUM_WORKERS = 4; // నిజమైన యాప్లో దీనిని పాస్ చేయాలి
if (finishedCount === NUM_WORKERS) {
console.log('చివరి వర్కర్ పూర్తి చేసింది. ప్రధాన థ్రెడ్కు తెలియజేస్తున్నాను.');
// 1. స్టేటస్ ఫ్లాగ్ను 1 (పూర్తయింది) కి సెట్ చేయండి
Atomics.store(sharedArray, 0, 1);
// 2. ఇండెక్స్ 0 పై వేచి ఉన్న ప్రధాన థ్రెడ్కు తెలియజేయండి
Atomics.notify(sharedArray, 0, 1);
}
};
నిజ-ప్రపంచ వినియోగ కేసులు మరియు అప్లికేషన్లు
ఈ శక్తివంతమైన కానీ సంక్లిష్టమైన టెక్నాలజీ వాస్తవానికి ఎక్కడ తేడాను చూపుతుంది? ఇది పెద్ద డేటాసెట్లపై భారీ, ప్యారలలైజబుల్ గణన అవసరమయ్యే అప్లికేషన్లలో రాణిస్తుంది.
- వెబ్ అసెంబ్లీ (Wasm): ఇది కిల్లర్ యూజ్ కేస్. C++, రస్ట్, మరియు గో వంటి భాషలకు మల్టీథ్రెడింగ్కు పరిపక్వ మద్దతు ఉంది. Wasm డెవలపర్లను ఈ ఇప్పటికే ఉన్న అధిక-పనితీరు గల, మల్టీ-థ్రెడెడ్ అప్లికేషన్లను (గేమ్ ఇంజిన్లు, CAD సాఫ్ట్వేర్, మరియు సైంటిఫిక్ మోడల్స్ వంటివి) బ్రౌజర్లో నడపడానికి కంపైల్ చేయడానికి అనుమతిస్తుంది, థ్రెడ్ కమ్యూనికేషన్ కోసం
SharedArrayBuffer
ను అంతర్లీన మెకానిజంగా ఉపయోగిస్తుంది. - ఇన్-బ్రౌజర్ డేటా ప్రాసెసింగ్: పెద్ద-స్థాయి డేటా విజువలైజేషన్, క్లయింట్-సైడ్ మెషిన్ లెర్నింగ్ మోడల్ ఇన్ఫరెన్స్, మరియు భారీ మొత్తంలో డేటాను ప్రాసెస్ చేసే శాస్త్రీయ సిమ్యులేషన్లను గణనీయంగా వేగవంతం చేయవచ్చు.
- మీడియా ఎడిటింగ్: హై-రిజల్యూషన్ చిత్రాలకు ఫిల్టర్లను వర్తింపజేయడం లేదా సౌండ్ ఫైల్పై ఆడియో ప్రాసెసింగ్ చేయడం వంటివి చంక్స్గా విభజించి బహుళ వర్కర్ల ద్వారా ప్యారలల్గా ప్రాసెస్ చేయవచ్చు, వినియోగదారునికి నిజ-సమయ ఫీడ్బ్యాక్ అందిస్తుంది.
- హై-పెర్ఫార్మెన్స్ గేమింగ్: ఆధునిక గేమ్ ఇంజిన్లు ఫిజిక్స్, AI, మరియు అసెట్ లోడింగ్ కోసం మల్టీథ్రెడింగ్పై ఎక్కువగా ఆధారపడతాయి.
SharedArrayBuffer
బ్రౌజర్లో పూర్తిగా నడిచే కన్సోల్-నాణ్యత గల గేమ్లను నిర్మించడం సాధ్యం చేస్తుంది.
సవాళ్లు మరియు తుది పరిగణనలు
SharedArrayBuffer
పరివర్తనాత్మకమైనది అయినప్పటికీ, ఇది సర్వరోగనివారిణి కాదు. ఇది జాగ్రత్తగా నిర్వహణ అవసరమయ్యే ఒక తక్కువ-స్థాయి సాధనం.
- సంక్లిష్టత: కాంకరెంట్ ప్రోగ్రామింగ్ చాలా కష్టమైనది. రేస్ కండిషన్స్ మరియు డెడ్లాక్స్ను డీబగ్ చేయడం చాలా సవాలుగా ఉంటుంది. మీ అప్లికేషన్ స్టేట్ ఎలా నిర్వహించబడుతుందో మీరు భిన్నంగా ఆలోచించాలి.
- డెడ్లాక్స్: ఒక డెడ్లాక్ ఎప్పుడు సంభవిస్తుందంటే, రెండు లేదా అంతకంటే ఎక్కువ థ్రెడ్లు శాశ్వతంగా బ్లాక్ చేయబడినప్పుడు, ప్రతి ఒక్కటి మరొకటి ఒక వనరును విడుదల చేయడం కోసం వేచి ఉంటుంది. మీరు సంక్లిష్టమైన లాకింగ్ మెకానిజంలను తప్పుగా అమలు చేస్తే ఇది జరగవచ్చు.
- భద్రతా ఓవర్హెడ్: క్రాస్-ఆరిజిన్ ఐసోలేషన్ అవసరం ఒక ముఖ్యమైన అడ్డంకి. ఇది థర్డ్-పార్టీ సేవలు, యాడ్స్, మరియు పేమెంట్ గేట్వేలతో ఇంటిగ్రేషన్లను బ్రేక్ చేయగలదు, అవి అవసరమైన CORS/CORP హెడర్లకు మద్దతు ఇవ్వకపోతే.
- ప్రతి సమస్యకు కాదు: సాధారణ బ్యాక్గ్రౌండ్ పనులు లేదా I/O ఆపరేషన్ల కోసం,
postMessage()
తో సాంప్రదాయ వెబ్ వర్కర్ మోడల్ తరచుగా సరళమైనది మరియు సరిపోతుంది. మీకు స్పష్టమైన, CPU-బౌండ్ బాటిల్నెక్ పెద్ద మొత్తంలో డేటాతో ఉన్నప్పుడు మాత్రమేSharedArrayBuffer
ను ఉపయోగించండి.
ముగింపు
SharedArrayBuffer
, Atomics
మరియు వెబ్ వర్కర్లతో కలిసి, వెబ్ డెవలప్మెంట్ కోసం ఒక నమూనా మార్పును సూచిస్తుంది. ఇది సింగిల్-థ్రెడెడ్ మోడల్ యొక్క సరిహద్దులను బద్దలు కొట్టి, బ్రౌజర్లోకి ఒక కొత్త తరగతి శక్తివంతమైన, పనితీరు గల, మరియు సంక్లిష్టమైన అప్లికేషన్లను ఆహ్వానిస్తుంది. ఇది గణనతో కూడిన తీవ్రమైన పనుల కోసం వెబ్ ప్లాట్ఫారమ్ను నేటివ్ అప్లికేషన్ డెవలప్మెంట్తో మరింత సమాన స్థాయిలో ఉంచుతుంది.
కాంకరెంట్ జావాస్క్రిప్ట్లోకి ప్రయాణం సవాలుతో కూడుకున్నది, ఇది స్టేట్ మేనేజ్మెంట్, సింక్రొనైజేషన్, మరియు భద్రతకు కఠినమైన విధానాన్ని కోరుతుంది. కానీ వెబ్లో సాధ్యమయ్యే దాని పరిమితులను అధిగమించాలని చూస్తున్న డెవలపర్లకు—నిజ-సమయ ఆడియో సింథసిస్ నుండి సంక్లిష్టమైన 3D రెండరింగ్ మరియు సైంటిఫిక్ కంప్యూటింగ్ వరకు—SharedArrayBuffer
ను మాస్టర్ చేయడం ఇకపై కేవలం ఒక ఎంపిక కాదు; ఇది తదుపరి తరం వెబ్ అప్లికేషన్లను నిర్మించడానికి ఒక ముఖ్యమైన నైపుణ్యం.